﻿using UnityEngine;
using System.Collections;

public class Steering2DBehavious : MonoBehaviour
{
    [Tooltip("交通工具脚本")]
    public Vehicle2DBehaviourScript vehicle2D;

    /// <summary>
    /// 减速模式
    /// </summary>
    public enum Deceleration
    {
        Fast = 1,
        Normal = 2,
        Slow = 3,
    }

    void Start()
    {
    }

    float tm = 0;
    public Vector2 Calculate()
    {
        tm += vehicle2D.deltaTime;
        if (tm % 10 > 5)
        {
            Debug.Log("回家.");
            return Arrive(Vector2.zero, Deceleration.Slow);
        }
        Debug.Log("巡逻");
        return Wander();
    }

    /// <summary>
    /// 靠近
    /// </summary>
    /// <param name="targetPos">目标坐标</param>
    /// <returns>操控力</returns>
    public Vector2 Seek(Vector2 targetPos)
    {
        var desiredVelocity = (targetPos - vehicle2D.pos2d).normalized * vehicle2D.maxSpeed;
        return (desiredVelocity - vehicle2D.velocity) / vehicle2D.deltaTime * vehicle2D.mass;
    }

    /// <summary>
    /// 离开
    /// </summary>
    /// <param name="targetPos">目标坐标</param>
    /// <returns>操控力</returns>
    public Vector2 Flee(Vector2 targetPos)
    {
        var desiredVelocity = (vehicle2D.pos2d - targetPos).normalized * vehicle2D.maxSpeed;
        return (desiredVelocity - vehicle2D.velocity) / vehicle2D.deltaTime * vehicle2D.mass;
    }

    /// <summary>
    /// 抵达
    /// </summary>
    /// <param name="targetPos">目标坐标</param>
    /// <param name="deceleration">慢速模式</param>
    /// <returns>操控力</returns>
    public Vector2 Arrive(Vector2 targetPos, Deceleration deceleration)
    {
        var toTarget = targetPos - vehicle2D.pos2d;
        var distance = toTarget.magnitude;
        if (distance <= 0)
        {
            return Vector2.zero;
        }

        const float DecelerationTweaker = 0.3f;
        var speed = distance / ((float)deceleration * DecelerationTweaker);
        speed = Mathf.Min(speed, vehicle2D.maxSpeed);

        // 因为已经magnitude 优化一次normalized
        var desiredVelocity = toTarget / distance * speed;
        return (desiredVelocity - vehicle2D.velocity) / vehicle2D.deltaTime * vehicle2D.mass;
    }

    /// <summary>
    /// 追逐
    /// </summary>
    /// <param name="evader">逃离者</param>
    /// <returns>操控力</returns>
    public Vector2 Pursuit(Vehicle2DBehaviourScript evader)
    {
        var toEvader = evader.pos2d - vehicle2D.pos2d;
        var dotTurn = vehicle2D.heading.Dot(toEvader);
        var relativeHeading = vehicle2D.heading.Dot(evader.heading);

        // 逃避者在前面 且 逃避者与自己面对 cos(18) = 0.95
        if (dotTurn > 0 && relativeHeading < -0.95)
        {
            return Seek(evader.pos2d);
        }

        // 预算时间等于距离除以速度和
        var lookaheadTime = toEvader.magnitude / (vehicle2D.maxSpeed + evader.speed);

        // 加上转角时间
        //lookaheadTime += (1 - dotTurn) * 0.5f;
        return Seek(evader.pos2d + evader.velocity * lookaheadTime);
    }

    /// <summary>
    /// 逃离
    /// </summary>
    /// <param name="pursuer">追逐者</param>
    /// <returns>操控力</returns>
    public Vector2 Evade(Vehicle2DBehaviourScript pursuer)
    {
        var toPursuer = pursuer.pos2d - vehicle2D.pos2d;

        // 恐吓半径
        //if (toPursuer.sqrMagnitude > 100) return Vector2.zero;

        // 预算时间等于距离除以速度和
        var lookaheadTime = toPursuer.magnitude / (vehicle2D.maxSpeed + pursuer.speed);
        return Flee(pursuer.pos2d + pursuer.velocity * lookaheadTime);
    }

    /// <summary>
    /// 巡逻
    /// </summary>
    /// <returns>操控力</returns>
    public Vector2 Wander()
    {
        // 随机得到一个前方巡逻圈位移 并接近
        var v = vehicle2D.heading * vehicle2D.wanderDistance;
        v += Random.insideUnitCircle * vehicle2D.wanderRadius;
        return Seek(vehicle2D.pos2d + v);
    }
}
